using System;
using System.Drawing;
using System.Collections.Generic;
using Clandestine.Engines.Field;

namespace Shlick
{
	using Object = Clandestine.Engines.Field.Object;
	
	public class ObjectMoveTool : Tool	
	{
		public override string Name { get { return "Move Object"; } }
		public MapDocument MapDocument { get; private set; } 
		private List<Object> objects;
		private List<Point> originalPositions = new List<Point>();
		private List<Point> mouseOffsets = new List<Point>(); // when we're called the mouse wont be at the object's origin, so move it relative to mouse's original position
		public override event ToolCompleteHandler ToolComplete;
		
		public ObjectMoveTool (MapDocument mapDocument)
		{
			this.MapDocument = mapDocument;
		}
	
		public override void Activated(params object[] args)
		{
			objects = (List<Object>)args[0];
			mouseOffsets.Clear();
        	originalPositions.Clear();
        	
        	// Get the mouse's current position so we can work out it's offset to each object.
			int tileX, tileY;
			this.MapDocument.ToolManager.GetMousePosition(out tileX, out tileY);
			
			// Work out the offset and remember it's original position for each object
			foreach (Object o in objects)
			{
				mouseOffsets.Add(new Point(tileX - o.Position.X, tileY - o.Position.Y));
				originalPositions.Add(o.Position);
			}
		}
		
        public override void Deactivated()
        {
        	// If we're interrupted, just revert to normal.
        	this.Reset();
        }
	
        public override void MouseDownLeft(int mouseX, int mouseY, int tileX, int tileY)
        {
            // Left-click: Complete Move
            
            // Reset positions so we can do it via Command -- don't bother making dirty.
        	for (int i = 0; i < objects.Count; i++)
        		objects[i].Position = originalPositions[i];
        		
        	// Do the move for each object separately but group them so the undo manager treats them as one.
        	List<ICommand> cmds = new List<ICommand>();
        	for (int i = 0; i < objects.Count; i++)
        		cmds.Add(new ObjectMoveCommand(objects[i], new Point(tileX - mouseOffsets[i].X, tileY - mouseOffsets[i].Y)));
        	this.MapDocument.CommandManager.Do(new CommandCollection("Move Object(s)", cmds));
        	
        	// Finished
        	if (ToolComplete != null)
        		ToolComplete();
        }
        
        public override void MouseUpLeft(int mouseX, int mouseY, int tileX, int tileY)
        {
        }
        
        public override void MouseDownRight(int mouseX, int mouseY, int tileX, int tileY)
        {
        	// Right-click: Cancel move
			this.Reset();
        	
        	// Finished
        	if (ToolComplete != null)
        		ToolComplete();
        }
        
        public override void MouseUpRight(int mouseX, int mouseY, int tileX, int tileY)
        {
        }
        
        public override void MouseMove(int mouseX, int mouseY, int tileX, int tileY)
        {
        	// Move objects as we move the mouse -- although this move will work out only temporary.
        	for (int i = 0; i < objects.Count; i++)
	        	if ((objects[i].Position.X != tileX) || (objects[i].Position.Y != tileY))
	        	{
		        	objects[i].Position = new Point(tileX - mouseOffsets[i].X, tileY - mouseOffsets[i].Y);
		        	objects[i].Dirty = true;
	       		}
        }
        
        public override void LevelChanged (Level oldLevel)
		{
			this.Reset();
			
			// Finished
        	if (ToolComplete != null)
        		ToolComplete();
		}
        
        protected virtual void Reset()
        {
        	// Reset positions
        	for (int i = 0; i < objects.Count; i++)
        	{
           		objects[i].Position = originalPositions[i];
        		objects[i].Dirty = true;
        	}
        }
	}
}

